package de.justphil.tcg.tcgserver.game.mechanics.property.properties;

import java.io.DataInput;
import java.io.IOException;
import java.util.List;

import de.justphil.tcg.tcgserver.commons.exceptions.TCGException;
import de.justphil.tcg.tcgserver.game.mechanics.event.Event;
import de.justphil.tcg.tcgserver.game.mechanics.event.Scheduler;
import de.justphil.tcg.tcgserver.game.mechanics.game.Game;
import de.justphil.tcg.tcgserver.game.mechanics.monster.Monster;
import de.justphil.tcg.tcgserver.game.mechanics.monster.MonsterList;
import de.justphil.tcg.tcgserver.game.mechanics.property.Property;
import de.justphil.tcg.tcgserver.game.mechanics.property.PropertyList;
import org.slf4j.Logger;
import static de.justphil.tcg.tcgserver.commons.logging.TCGLogging.*;

public class Regeneration extends Property {

	private static final Logger log = gameLogger(Regeneration.class);
	private static final double INTERVAL = 1.0;
	private Scheduler scheduler;

	public Regeneration(Game game) {

		super(game);

		if (game != null) {
			this.scheduler = game.getScheduler();
		}
	}

	@Override
	public int getType() {

		return PROPERTY_REGENERATION;
	}

	@Override
	protected MonsterList handleEvent(Event event) {

		MonsterList monsters;
		switch (event.getType()) {

		case Event.EVENT_HEALING:

			monsters = new MonsterList();
			monsters.add(handleHealing((Monster) event.getData()));
			return monsters;

		default:
			assert false;
			break;
		}
		return null;
	}

	private Monster handleHealing(Monster monster) {

		if (getMonster().equals(monster)) {

			boolean healed = false;

			log.debug("Trying to heal Monster ({}).", new Object[] { monster });

			PropertyList properties = monster.getProperties(PROPERTY_DAMAGE);

			if (properties.size() > 0) {

				monster.removeProperty(properties.getFirst());

				healed = true;

				log.info("Healed Monster ({}).", new Object[] { monster });

			} else {

				log.debug("Nothing to heal at Monster ({}).",
						new Object[] { monster });
			}

			try {
				scheduler.scheduleFirst(
						new Event(Event.EVENT_HEALING, monster), INTERVAL);

			} catch (TCGException e) {
				assert false: e.getMessage();
			}

			if (healed) {

				return monster;
			}
		}
		return null;
	}

	@Override
	protected List<Integer> getListeningEventTypes() {

		List<Integer> types = super.getListeningEventTypes();
		types.add(Event.EVENT_HEALING);

		return types;
	}

	@Override
	protected MonsterList handleActivation() {

		try {
			scheduler.scheduleFirst(
					new Event(Event.EVENT_HEALING, getMonster()), INTERVAL);
		} catch (TCGException e) {
			assert false: e.getMessage();
		}

		return null;
	}

	@Override
	protected MonsterList handleDeactivation() {

		scheduler.unschedule(new Event(Event.EVENT_HEALING, getMonster()));

		return null;
	}

	@Override
	public void readData(Game game, DataInput in) throws IOException {

		super.readData(game, in);

		scheduler = getScheduler();
	}
}
